package com.zx.service;

import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zx.base.mybatis.ServiceImpl;
import com.zx.mapper.UserMapper;
import com.zx.pojo.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.nio.charset.StandardCharsets;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
    @Resource
    private UserMapper userMapper;

    @Override
    public User getUser(User user) {
        return userMapper.getUser(user);
    }

//    /**
//     * 使用MD5加密方式
//     * 1、不可逆加密（只能加密，不能解密）
//     * 2、相同的明文一定加密为相同的密文
//     * 3、不同的明文一定加密为不同的密文
//     *
//     * @param plaintextPassword
//     * @return
//     * @throws IllegalArgumentException
//     */
//    public static String encryptPassword(String plaintextPassword) throws IllegalArgumentException {
//        System.out.println("----------  进入加密方式");
//        String salt = "czkt"; // 盐值
//        MD5 md5 = new MD5();
//        int length = plaintextPassword.getBytes(StandardCharsets.UTF_8).length;
//        length = length % 3 + 3;
//        md5.setSalt(salt.getBytes(StandardCharsets.UTF_8));
//        String enPassword = plaintextPassword;
//        for (int i = 0; i < length; i++) {
//            enPassword = md5.digestHex(enPassword);
//            System.out.println(enPassword + "   " +  (i + 1)+ "__________________");
//        }
//        return enPassword;
//    }

    /**
     * 使用Shiro中的加密方式
     *
     * @param plaintextPassword
     * @return
     * @throws IllegalArgumentException
     */
    public String encryptPassword(Object plaintextPassword) throws IllegalArgumentException {
        String salt = "czkt";
        Md5Hash md5Hash = new Md5Hash(plaintextPassword, salt, 2);
        return md5Hash.toString();
    }


    /**
     * 保存或修改用户（如果有主键ID则修改，没有则保存）
     *
     * @param user 用户
     * @return
     * @CachePut 首先执行方法体，执行完毕后根据参数设置进行缓存覆盖
     * value: 缓存名称
     * key: 缓存的键值
     * condition: 满足条件的调用，结果才会被缓存（不指定时相当于true-缓存）
     * unless: 不合适的返回，结果不缓存（不指定时相当于false-缓存）
     * 总结: 当condition=false一定不缓存；当condition=true且unless=true不缓存；当condition=true且unless=false缓存
     */
    @Override
    @CachePut(value = "user", key = "#user.usrId", condition = "#user!=null", unless = "#result==null")
    @CacheEvict(value = "userPage", allEntries = true)
    public User saveUser(User user) {
        user.setUsrPassword(encryptPassword(user.getUsrPassword()));
        boolean isok = super.saveOrUpdate(user); // 使用MyBatis-Plus提供的方法
        if (isok) {
            return super.getById(user.getUsrId());
        }
        return null;
    }

    /**
     * 根据ID删除用户
     *
     * @param usrId
     */
    @Override
    @CacheEvict(value = "userPage", allEntries = true)
    public boolean deleteUser(Long usrId) {
        return super.removeById(usrId);
    }

    /**
     * 修改密码
     *
     * @param usrId       用户ID
     * @param newPassword 新密码
     * @return
     * @CachePut 首先执行方法体，执行完毕后根据参数设置进行缓存覆盖
     * value: 缓存名称
     * key: 缓存的键值
     * condition: 满足条件的调用，结果才会被缓存（不指定时相当于true-缓存）
     * unless: 不合适的返回，结果不缓存（不指定时相当于false-缓存）
     * 总结: 当condition=false一定不缓存；当condition=true且unless=true不缓存；当condition=true且unless=false缓存
     */
    @Override
    @CachePut(value = "user", key = "#usrId", condition = "#usrId>=1", unless = "#result==null")
    @CacheEvict(value = "userPage", allEntries = true)
    public User resetPassword(Long usrId, String newPassword) {
        User user = new User();
        user.setUsrId(usrId);
        user.setUsrPassword(encryptPassword(newPassword));
        int updok = userMapper.updateById(user);
        if (updok == 1) {
            user = userMapper.selectById(usrId);
        } else {
            user = null;
        }
        return user;
    }

    /**
     * 根据ID获得单个用户对象
     *
     * @param usrId
     * @return
     */
    @Override
    @Cacheable(value = "user", keyGenerator = "keyGenerator")
    public User getUserById(Long usrId) {
        return super.getById(usrId);
    }

    /**
     * 分页获得用户数据
     *
     * @Cacheable 首先查缓存有就返回，没有就执行方法，方法返回不为空添加缓存
     * value: 缓存名称，可以多个
     * key: 缓存的键值
     * keyGenerator = "keyGenerator": 缓存的key自动生成
     * condition: 满足条件的调用，结果才会被缓存（不指定时相当于true-缓存）
     * unless: 不合适的返回，结果不缓存（不指定时相当于false-缓存）
     * 总结: 当condition=false一定不缓存；当condition=true且unless=true不缓存；当condition=true且unless=false缓存
     */
    @Override
    @Cacheable(value = "userPage", key = "#page.getCurrent() + '-' + #page.getSize() + '-' + #usrName + '-' + #roleId", condition = "#page.getCurrent() != null and #page.getSize() != null", unless = "#result == null")
    public IPage<User> findUsers(String usrName, Long roleId, Page page) {
        return super.getPage(page, new User(usrName, roleId));
    }
}
